#include "Bot.h"
#include "MDP.h"
using namespace std;

// "python sample_bots/python/GreedyBot.py" \

//constructor
Bot::Bot()
{

};

//plays a single game of Ants.
void Bot::playGame()
{
    //reads the game parameters and sets up
    cin >> state;
    state.setup();
    endTurn();

    row = state.rows; col = state.cols;
    attackradius = state.attackradius;
    radius = state.viewradius;
    seen = new bool[row*col];
    hills = (int* )malloc(sizeof(int)*cols*rows);
    resetSeen();

    //continues making moves while the game is not over
    while(cin >> state)
    {
        state.updateVisionInformation();
	if(state.turn%150 == 0){
		resetSeen();
	}
        makeMoves();
        endTurn();
    }
};


visSquare::visSquare(){
	reward = 0;
	updatable = true;
}

void Bot::resetSeen(){
	for(int i =0; i<row; i++){
		for(int j=0; j<col; j++){
			*(seen+i*col+j) = false;
		}
	}
}
	

//makes the bots moves for the turn
void Bot::makeMoves()
{
    state.bug << "turn " << state.turn << ":" << endl;
    state.bug << state << endl;

    for(int i=0; i<row; i++){
	    for(int j=0; j<col; j++){
		    if(state.grid[i][j].isVisible){
			    *(seen+i*col+j) = true;
		    }
	    }
    }
    
    int army = 0, enemy = 0;
    int enemyReward = -150;
	
    struct visSquare vs[row][col];
    
    for (int i=0; i<row; i++){
	    for (int j=0; j<col; j++){
		    struct Square sq = state.grid[i][j];
		    if(!(*(seen+i*col+j))){
			    vs[i][j].reward = unseenReward;
			    vs[i][j].updatable = false;
		    }else if(!sq.isVisible){
			    vs[i][j].reward = invisibleReward;
			    vs[i][j].updatable = false;
		    }else if(sq.ant == 0){
			    vs[i][j].reward = myAntReward;
			    vs[i][j].updatable = false;
			    army++;
		    }else if(sq.ant > 0){
			    vs[i][j].reward = enemyReward;
			    vs[i][j].updatable = false;
			    for (int r=-attackradius; r<attackradius; r++){
				    for (int c=-attackradius; c<attackradius; c++){
					    bool underattack = r*r+c*c<=attackradius*attackradius;
					    int ur = i+r>=0?(i+r)%row:i+r+row, uc = j+c>=0?(j+c)%col:j+c+col;
					    if(underattack){
						    vs[ur][uc].reward = enemyReward;
						    vs[ur][uc].updatable = false;
					    }
				    }
			    }
			    enemy++;
		    }else if(sq.isWater){
			    vs[i][j].reward = waterReward;
			    vs[i][j].updatable = false;
		    }else if(sq.isFood){
			    vs[i][j].reward = foodReward;
			    vs[i][j].updatable = false;
		    }else if(sq.isHill && sq.hillPlayer == 0){
			    vs[i][j].reward = myHillReward;
			    vs[i][j].updatable = false;
		    }else if(sq.isHill && sq.hillPlayer != 0){
			    vs[i][j].reward = enemyHillReward;
			    vs[i][j].updatable = false;
		    }
	    }
    }

    for (int iter=0; iter<iteration; iter++){
	    for (int j=0; j<col; j++){
		    for (int i=row-1; i>=0; i--){
			    update((struct visSquare *)vs, i, j);
		    }
	    }
	    for (int i=row-1; i>=0; i--){
		    for (int j=col-1; j>=0; j--){
			    update((struct visSquare *)vs, i, j);
		    }
	    }
    }

//     for (int j=0; j<col; j++){
// 	    for (int i=row-1; i>=0; i--){
// 		    cout << vs[i][j].reward << " ";
// 	    }
// 	    cout << endl;
//     }

    //picks out moves for the rest ants which are not guarding the hill
    for(int ant=0; ant<(int)state.myAnts.size(); ant++)
    {
        int reward[TDIRECTIONS], maxMove = -99999;
        int direction = 0;
	Location loc = state.myAnts[ant];
	
	for (int i=0; i<TDIRECTIONS; i++){
		reward[i] = getReward((struct visSquare *)vs, loc.row, loc.col, i);
		if(reward[i]>maxMove){
			maxMove = reward[i];
			direction = i;
		}
	}
	
	
	//cout << "maxMove : " << maxMove << " direction : " << direction << endl;
	
	if(maxMove>vs[loc.row][loc.col].reward){
		setReward((struct visSquare *)vs, loc.row, loc.col, direction, myAntReward);
		if(direction==0){
			direction = 2;
		}else if(direction==2){
			direction = 0;
		}
		state.makeMove(state.myAnts[ant], direction);
		vs[loc.row][loc.col].reward = 0;
	}
    }

    state.bug << "time taken: " << state.timer.getTime() << "ms" << endl << endl;
};



// Updates the reward of each square in the visible area of an ant
void Bot::update(struct visSquare *vs, int r, int c){
	struct visSquare *curvs = vs+r*col+c;
	if(!(*curvs).updatable){
		return;
	}
	
	int maxReward = 0;
	for (int i=0; i<4; i++){
		maxReward = maxReward>getReward(vs, r, c, i)?maxReward:getReward(vs, r, c, i);
	}
	
	(*curvs).reward = maxReward + stepCost;
}

int Bot::getReward(struct visSquare *vs, int r, int c, int direction){
	if(direction == 0){
		r = (r+1)%row;
		return (*(vs+r*col+c)).reward;
	}else if(direction == 1){
		c = (c+1)%col;
		return (*(vs+r*col+c)).reward;
	}else if(direction == 2){
		r = (r-1)>=0?(r-1):(r-1)+row;
		return (*(vs+r*col+c)).reward;
	}else if(direction == 3){
		c = (c-1)>=0?(c-1):(c-1)+col;
		return (*(vs+r*col+c)).reward;
	}
}

void Bot::setReward(struct visSquare *vs, int r, int c, int direction, int reward){
	if(direction == 0){
		r = (r+1)%row;
		(*(vs+r*col+c)).reward = reward;
	}else if(direction == 1){
		c = (c+1)%col;
		(*(vs+r*col+c)).reward = reward;
	}else if(direction == 2){
		r = (r-1)>=0?(r-1):(r-1)+row;
		(*(vs+r*col+c)).reward = reward;
	}else if(direction == 3){
		c = (c-1)>=0?(c-1):(c-1)+col;
		(*(vs+r*col+c)).reward = reward;
	}
}

//finishes the turn
void Bot::endTurn()
{
    if(state.turn > 0)
        state.reset();
    state.turn++;

    cout << "go" << endl;
};
